使用 Docker 资源
此教程中的所有示例镜像都在 https://github.com/lulaide/docker-example/
Volume 存储卷

Volume 是 Docker 官方管理的“持久化存储机制”,用来保存容器生命周期之外仍然保留的数据,例如数据库、日志、文件存储等。
容器删了 → 数据还在 容器更新、重建 → 数据不丢
Volume 是 Docker 推荐的数据持久化方式,比 bind mount 更安全、更便携,且可跨容器共享。
Volume 三种类型:
Named Volume(命名卷)——最常用
由 Docker 管理,默认存储在:
/var/lib/docker/volumes/<volume_name>/_data/
创建命名卷
docker volume create <volume_name>
查看所有卷
docker volume ls
删除卷
docker volume rm <volume_name>
这里使用一个 Minecraft 服务器利用 Volume 来保存 主世界地图 的例子:
创建储存卷
docker volume create mc_world
运行 Minecraft 容器,并挂载储存卷
docker run -itd -p 25565:25565 -v mc_world:/app/world --name mc1.12.2 ghcr.io/lulaide/paper:1.12.2
进入游戏后对世界进行一些修改,然后关闭服务器。

docker stop mc1.12.2
现在查看一下储存卷中的数据:
docker volume inspect mc_world
输出如下
[
{
"CreatedAt": "2025-xx-xxTxx:xx:xx+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/mc_world/_data",
"Name": "mc_world",
"Options": null,
"Scope": "local"
}
]
此目录内的内容即为 Minecraft 世界数据,原本 world 目录下的文件都在这里:
$ ls /var/lib/docker/volumes/mc_world/_data
advancements data level.dat level.dat_old playerdata region session.lock stats uid.dat
现在我们把游戏版本换为1.21.1,重新运行容器,并挂载同一个储存卷:
docker run -itd -p 25565:25565 -v mc_world:/app/world --name mc1.21.1 ghcr.io/lulaide/paper:1.21.1
再次进入游戏,发现之前的世界数据都还在,并且版本已经升级到 1.21.1 了:

关闭服务器
docker stop mc1.21.1
删除容器
docker rm mc1.21.1
可以看到储存卷中的数据依然存在:
$ ls /var/lib/docker/volumes/mc_world/_data
advancements data datapacks entities level.dat level.dat_old paper-world.yml playerdata region session.lock stats uid.dat
特点:
- 自动管理路径
- 跨容器共享
- 容器删除不会删除卷
Anonymous Volume(匿名卷)
及其不推荐使用匿名卷,因为无法轻易管理和定位数据。 匿名卷是没有命名的 Volume,Docker 会自动分配一个随机名称。只有两种情况会出现匿名卷:
镜像里写了 VOLUME 指令
这里以官方的 MySQL 镜像为例:
docker run --rm -e MYSQL_ROOT_PASSWORD=root mysql:latest
运行前只有一个卷:
$ docker volume ls
DRIVER VOLUME NAME
local mc_world
运行后会多出一个匿名卷:
$ docker volume ls
DRIVER VOLUME NAME
local ed7410e0fe487b6b96975b935d6908e2cf3a2448983af184e2794a9e7c1fe8a2
local mc_world
这里储存这数据库数据
$ ls /var/lib/docker/volumes/ed7410e0fe487b6b96975b935d6908e2cf3a2448983af184e2794a9e7c1fe8a2/_data
auto.cnf ca-key.pem '#ib_16384_0.dblwr' ibtmp1 mysql.ibd private_key.pem sys
binlog.000001 ca.pem '#ib_16384_1.dblwr' '#innodb_redo' mysql.sock public_key.pem undo_001
binlog.000002 client-cert.pem ib_buffer_pool '#innodb_temp' mysql_upgrade_history server-cert.pem undo_002
binlog.index client-key.pem ibdata1 mysql performance_schema server-key.pem
更推荐的做法是使用命名卷,自己创建并挂载到容器中:
docker volume create mysql_data
docker run -d -e MYSQL_ROOT_PASSWORD=root -v mysql_data:/var/lib/mysql mysql:latest
运行容器时使用 -v 或 --volume 但没有指定卷名
创建匿名卷
docker run -v /app/ --rm ubuntu sh -c 'echo "Anonymous Volume" > /app/output.txt'
查看有哪些卷
docker volume ls
你会发现多了一个名字一长串的卷:
DRIVER VOLUME NAME
local 4878daef9a83732adc44a771a5cd82a8a2730ea567a229487a4cbbcac4354fed
local mc_world
我们写入的 output.txt 文件的确保存在这个卷下。
cat /var/lib/docker/volumes/4878daef9a83732adc44a771a5cd82a8a2730ea567a229487a4cbbcac4354fed/_data/output.txt
Anonymous Volume
Host Bind Mount(绑定挂载)
直接把宿主的目录挂载到容器中:
docker run -v /path/on/host:/path/in/container ...
这种方式更灵活,可以直接访问宿主机的文件系统,但需要注意权限和路径问题。 简单理解:
容器内看到的路径 = 宿主机真实文件 修改任意一边 = 两边实时同步
Bind Mount 不属于 Docker Volume,它属于 Linux 内核的 bindfs(bind mount)机制。 当你执行:
-v /host:/container
Docker 并没有移动文件,也没有创建卷,只做了一件事: 宿主机 /host 映射为容器中的 /container 这部分行为在 namespace + mount namespace 下实现。
Network 网络
安装 docker 之后,默认会创建三种网络类型:
- bridge(默认网络)
- host(直接使用宿主机网络)
- none(无网络)
还有其他类型:
- macvlan(自定义 MAC 地址,适合物理网络集成)
- ipvlan(类似 macvlan,但更灵活)
- overlay(跨主机网络,Swarm 模式使用)
bridge(默认网络)
最常用,用得最多。 特点: Docker 创建一个虚拟交换机:docker0 容器通过 veth pair 接入 提供独立的内部 IP(如 172.17.0.x) 容器与容器之间可互通 外部访问需要端口映射 -p 示例: 注意创建自定义 bridge 网络网络之前只有一个 docker0 网络的默认桥接网络,创建自定义桥接网络后会多出一个新的桥接网络:
...
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 2a:b8:a6:3e:1e:47 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
创建之后
...
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 2a:b8:a6:3e:1e:47 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
4: br-44c8aaa34eec: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 2e:65:bc:e1:c2:f7 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-44c8aaa34eec
valid_lft forever preferred_lft forever
docker network create mynet
docker run --network mynet nginx
适用场景:单机部署、容器互联
host(直接使用宿主机网络)
容器与宿主机共享网络命名空间: 无虚拟网卡 无 docker0 能使用,不能创建、不能删除、不能修改 性能最好 不需要 -p,直接监听宿主的端口 容易端口冲突 示例:
docker run --network host nginx
适用场景: 高性能网络服务(数据库、监控) 需要访问宿主机局域网广播
none(无网络)
容器没有网络接口 适合安全隔离
macvlan(自定义 MAC 地址)
每个容器获得:
- 局域网真实 IP
- 独立 MAC 地址
示例: 创建 macvlan 网络:
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 pubnet
运行容器并指定 IP:
docker run -it --rm --network pubnet --ip 192.168.1.100 alpine sh
查看一下容器内的网络配置:
6: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether aa:b9:f2:57:29:d8 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
valid_lft forever preferred_lft forever
容器可被局域网设备直接访问。
Docker 创建 macvlan 网络时 --subnet 与 --gateway 只是 Docker 内部的“地址管理器”(IPAM),并不是实际网络必须使用的网段。 如果你打算让容器通过 DHCP 获取真实 IP,则可以随便填写“假网段 / 假网关”,甚至完全不使用。
ipvlan(类似 macvlan,但更灵活)
IPvlan(IPVLAN)是 Linux 内核的一种虚拟网络接口技术,与 Macvlan 类似,但逻辑完全不同。这里简单了解一下即可。 IPvlan 不给每个容器创建独立 MAC,而是全部共享宿主机的 MAC,只区分 IP。
创建模式为 l2 的 ipvlan 网络:
docker network create -d ipvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
-o ipvlan_mode=l2 \
ipvlan0
| 项目 | IPvlan L2 | IPvlan L3 | IPvlan L3S |
|---|---|---|---|
| 工作层级 | 二层(Layer 2) | 三层(Layer 3) | 三层(共享子网) |
| MAC 地址 | 所有容器共享宿主机 MAC | 所有容器共享宿主机 MAC | 所有容器共享宿主机 MAC |
| IP 网段要求 | 必须和宿主机同网段 | 容器必须使用不同网段 | 与宿主机相同网段 |
| DHCP 支持 | ✔ 支持(广播可达) | ❌ 不支持(广播不转发) | ❌ 不支持 |
| 容器→外部网络 | 通过物理网络直接通通信 | 通过宿主机路由转发 | 也通过宿主机转发 |
| 容器←外部网络访问 | 直接访问(像 macvlan) | 需额外路由 | 需路由,但同网段更方便 |
| 容器间互通 | 需要辅助路由(默认隔离) | 宿主机做三层转发 | 宿主机做三层转发 |
| 容器访问宿主机 | 默认不通(需创建 ipvlan 子接口) | 默认不通(需路由) | 默认不通(需路由) |
CPU、内存、GPU 资源
CPU
- --cpus 限制容器可用的 CPU 数(1.5 表示 1.5 个核心)
- --cpuset-cpus 指定容器可使用哪些 CPU 核(如 0-3)
docker run --cpus="2.5" nginx
docker run --cpuset-cpus="0,2" nginx
内存
- --memory 限制容器可用的内存大小(如 512m、2g)
- --memory-swap 内存 + swap 总量
docker run -m 512m --memory-swap 1g nginx
GPU
- --gpus 指定 GPU 数量(如 all, 0, 0,1)
docker run --gpus all nvidia/cuda:12.0-base
docker run --gpus '"device=0,1"' nvidia/cuda:12.0-base